//#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
#define pr_fmt(fmt) "%s:%s: " fmt, KBUILD_MODNAME, __func__
#include <linux/skbuff.h>
#include <linux/gfp.h>
#include <linux/module.h>    // included for all kernel modules
#include <linux/kernel.h>    // included for KERN_INFO
#include <linux/init.h>      // included for __init and __exit macros
#include <linux/net.h>
#include <linux/netfilter.h>
#include <linux/net_namespace.h>
#include <linux/vmalloc.h>

#include <linux/netfilter_ipv4.h>

MODULE_LICENSE("GPL");
MODULE_AUTHOR("Noggew");
MODULE_DESCRIPTION("hello packet");

static struct nf_hook_ops nfho;   //net filter hook option struct
char *protocol;

unsigned int my_hook(void *priv,
                     struct sk_buff *skb,  // linux/skbuff.h
                     const struct nf_hook_state *state
                     )
{
  switch (skb->inner_protocol_type) {
  case ENCAP_TYPE_ETHER:
    protocol = "eth";
    break;
  case ENCAP_TYPE_IPPROTO:
    protocol = "ip";
    break;
  default: ;
    protocol = "nop";
  }
  pr_info("\ndev:%s\nproto:%d"
          , skb->dev->name
          , skb->inner_protocol_type
  );
  return NF_ACCEPT;
}

static int __init hello_init(void) {
  struct net *net;  // net/net_namespace.h
  pr_info("starting");
  //init_filter_if();
  protocol = kmalloc(9 * sizeof(char), GFP_KERNEL);
  nfho.hook = my_hook;
  nfho.hooknum = 0 ; //NF_IP_PRE_ROUTING;
  nfho.pf = PF_INET;
  nfho.priority = NF_IP_PRI_FIRST;
  for_each_net(net) {
    /* pr_info("register net:%p", net); */
    nf_register_net_hook(net, &nfho);
  }
  return 0;    // Non-zero return means that the module couldn't be loaded.
}

static void __exit hello_cleanup(void) {
  struct net *net;
  pr_info("cleaning");
  for_each_net(net) {
    /* pr_info("unregister net:%p", net); */
    nf_unregister_net_hook(net, &nfho);
  }
  kfree(protocol);
  pr_info("exiting");

}

module_init(hello_init);
module_exit(hello_cleanup);
